package org.example.core.security.filter;

import org.apache.commons.lang3.StringUtils;
import org.example.base.common.entity.TRequestLogEntity;
import org.example.base.common.model.TRequestLogModel;
import org.example.base.common.service.TRequestLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Timestamp;
import java.util.Enumeration;
import java.util.Objects;

import static org.apache.xml.serializer.Method.UNKNOWN;

/**
 * Description: 请求日志过滤器
 * Date: 2024/1/31 20:35
 */
@Component
public class RequestLogFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(RequestLogFilter.class);

    public static final String X_FORWARDED_FOR = "x-forwarded-for";

    public static final String PROXY_CLIENT_IP = "Proxy-Client-IP";

    public static final String WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";

    public static final String X_REAL_IP = "X-Real-IP";

    public static final String LOCAL_IP_V4 = "127.0.0.1";

    public static final String LOCAL_IP_V6 = "0:0:0:0:0:0:0:1";

    public static final String CDN_SRC_IP = "cdn-src-ip";

    @Autowired
    private TRequestLogService tRequestLogService;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        TRequestLogModel requestLogModel = new TRequestLogModel();
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Headers", "Origin,Content-Type,Accept,token,Cookie,X-Requested-With,authorization");
        res.setHeader("Access-Control-Allow-Methods", "*");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
        res.setHeader("Access-Control-Allow-Credentials","true");
        if ("OPTIONS".equals(((HttpServletRequest) request).getMethod())) {
            res.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        String uri = servletRequest.getRequestURI();
        String ipAddress = getIpAddress(servletRequest);
        requestLogModel.setUri(uri);
        // TODO: 2024/1/31 暂时先不写
        requestLogModel.setName("");
        requestLogModel.setIp(ipAddress);
        long beginTime = System.currentTimeMillis();
        chain.doFilter(request, res);
        long endTime = System.currentTimeMillis();
        requestLogModel.setExecuteTime(endTime - beginTime);
        logger.info("------>uri:{}<--------", uri);
        logger.info("------>ipAddress:{}<--------", ipAddress);
        tRequestLogService.add(requestLogModel);
    }

    /**
     * 获取请求IP.
     *
     * @return String ip
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = null;
        Enumeration<?> enu = request.getHeaderNames();
        while (enu.hasMoreElements()) {
            String name = (String) enu.nextElement();
            if (CDN_SRC_IP.equalsIgnoreCase(name)
                    || X_FORWARDED_FOR.equalsIgnoreCase(name)
                    || PROXY_CLIENT_IP.equalsIgnoreCase(name)
                    || WL_PROXY_CLIENT_IP.equalsIgnoreCase(name)
                    || X_REAL_IP.equalsIgnoreCase(name)) {
                ip = request.getHeader(name);
            }
            if (org.apache.commons.lang3.StringUtils.isNotBlank(ip)) {
                break;
            }
        }
        if (StringUtils.isBlank(ip)) {
            ip = request.getRemoteAddr();
        }

        if (ip.equals(LOCAL_IP_V4) || ip.equals(LOCAL_IP_V6)) {
            // 根据网卡取本机配置的IP
            InetAddress inet = null;
            try {
                inet = InetAddress.getLocalHost();
                ip = inet.getHostAddress();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        return ip;
    }
}
